<?php

// ---------------------------------------------------------------------------------------
//
// rFactor Server Query PHP Class by Rene - rene@wiesental-racing.de
//                                          www.wiesental-racing.de
//
// Das Script kann gerne jederzeit ge�ndert oder erweitert werden. Vorrausetzung
// daf�r ist, dass dieser komplette Kommentarblock und die beiliegende ReadMe erhalten bleiben.
// Es w�re sch�n, wenn ihr eigene Erweiterungen/Verbesserungen an mich sendet, damit ich
// sie zentral aufnehmen kann und alle etwas davon haben. (9.6.2006)
//
// Der Code wurde unter PHP 4.2.2 und 4.3.11 getestet, m�sste aber auch unter PHP 5 lauff�hig sein.
// F�r Fehler irgendeiner Art die durch die Benutzung des Code veruracht werden �bernehme ich
// selbstverst�ndlich keinerlei Haftung.
//
// ---------------------------------------------------------------------------------------


define("HDR_LEN", 16);


if (!class_exists("rFPluginQuery"))
{

class rFPluginQuery
{
	var $ip;						// IP address of server
	var $port;					// Server query port
	
	var $read_blocked;		// Determines whether to use blocking socket or not
	
	var $prot_ver;



	function rFPluginQuery($host, $port, $read_blocked = true)
	{
		$this->ip = gethostbyname($host);
		$this->port = $port;	
		$this->read_blocked = $read_blocked;	
		$this->cmd_result = false;
	}
	
	
	function _readFromSocket($socket, $num_bytes, $timeout)
	{
		$response = "";
		
		if ($this->read_blocked)
		{
			socket_set_blocking($socket, true);    
			socket_set_timeout($socket, $timeout, 0);
			
			$response = fread($socket, $num_bytes);			
		}
		else
		{		
			$start = time();		
	
			socket_set_blocking($socket, false);		
		
			do
			{			
				$response .= fread($socket, $num_bytes);
				$got_data = strlen($response) >= $num_bytes;			
			} while (!$got_data && ((time() - $start) < $timeout));
		}

	   return $response;
	}
	

	// Send a command to the server
	function _sendCommand($command, $timeout = 5)
	{
		$response = "";
		
		$command = "rFSQ_" . $command;

		// First of all open a socket
		if ($socket = @fsockopen("udp://" . $this->ip, $this->port))
		{
			// Set communication properties
			socket_set_blocking($socket, true);      
                        socket_set_timeout($socket, $timeout, 0);
      
	      // Send the command
	      if (fwrite($socket, $command, strlen($command)) == strlen($command))
	      {
	      	// Read server response
	      	$hdr = $this->_readFromSocket($socket, HDR_LEN, $timeout);
	      	if (strlen($hdr) == HDR_LEN)
	      	{
	      		if (($data_size = $this->_ShortFromBuffer($hdr, 0x0C)) > 0)
	      		{	      		
	      			$response = $this->_readFromSocket($socket, $data_size, $timeout);
	      		}
	      	}
	      }
	      else
	      {
	      	// TODO: Error -> the command was not completely written
	      }

	      // Close socket
	      fclose($socket);
		}
		else
		{
			// TODO: Error message
		}
		
		return $response;
	}
	
	function _ByteFromBuffer($buffer, $idx)
	{
		return ord($buffer[$idx]);
	}
	
	
	function _ShortFromBuffer($buffer, $idx)
	{
		$shortval =  ord($buffer[$idx]) | (ord($buffer[$idx+1]) << 8);
	
		return $shortval;
	}
	

	function _LongFromBuffer($buffer, $idx)
	{
		$longval =  ord($buffer[$idx]) | (ord($buffer[$idx+1]) << 8) | (ord($buffer[$idx+2]) << 16) | (ord($buffer[$idx+3]) << 24);
	
		return $longval;
	}

	
	function _StringFromBuffer($buffer, $max_len, $idx)
	{
		$result = "";
		$i = 0;
	
		while (($buffer[$idx] != "\x00") && ($i < $max_len))
		{
			$result .= $buffer[$idx++];
			$i++;
		}

		return $result;
	}
}

}

?>